#include "mainwindow.h"
#include  <QApplication>

#include<boost/asio.hpp>
#include<boost/thread.hpp>
#include<boost/timer.hpp>
#include<boost/array.hpp>
#include<boost/date_time.hpp>

using namespace std;

boost::posix_time::ptime             epoch(boost::gregorian::date(1970,boost::gregorian::Jan,1));
boost::system::error_code            serial_error;
boost::asio::io_service              serial_service;
boost::asio::serial_port             sp(serial_service, "/dev/ttyUSB0");

ofstream out("out.txt");

class control:public MainWindow
{

    public:
        control(boost::asio::io_service& io1,boost::asio::io_service& io2):
            mill(1),
            sec(1),
            timer1(io1, boost::posix_time::milliseconds(mill)),
            timer2(io2, boost::posix_time::seconds(sec) ),
            counter(0),
            seq(0)
        {
            timer1.async_wait(boost::bind(&control::tick1, this));
            timer2.async_wait(boost::bind(&control::tick2, this));
        }

        void tick1();
        void tick2();
        void readSerial();

    private:
        int mill;
        int sec;//初始化在timer之前
        boost::asio::deadline_timer          timer1;
        boost::asio::deadline_timer          timer2;
        boost::array< u_char, 10 >           send_buf;
        boost::array< u_char, 10 >           read_buf;

        double counter;
        int seq;
};


void control::tick1()
{
    counter++;
    seq++;
    auto speed = int(800*sin((2*M_PI)/(mill*1000.0)*counter));

    append_data1(speed);

    send_buf.at(0)=0x01;
    send_buf.at(1)=0xff;
    send_buf.at(2)=(speed>>8);
    send_buf.at(3)=(speed&0x00ff);

    std::size_t write_len   = boost::asio::write(sp, boost::asio::buffer(send_buf), boost::asio::transfer_all(), serial_error);

    timer1.expires_at(timer1.expires_at() + boost::posix_time::milliseconds(mill)  );
    timer1.async_wait( boost::bind(&control::tick1, this));
}

void control::tick2()
{
    cout<<"write srial freqence : "<<seq<<endl;
    seq=0;

    timer2.expires_at(timer2.expires_at() + boost::posix_time::seconds(sec) );
    timer2.async_wait( boost::bind(&control::tick2, this));
}


void  control::readSerial()
{
    float   pitch_angle=0;
    u_char  head[2];
    bool    ok=1;
    while(ok)
    {
        std::size_t read_len = boost::asio::read(sp, boost::asio::buffer(&head,2), boost::asio::transfer_all(), serial_error);

        if((head[0]==0xAA)&&(head[1]==0xAA))
        {
           std::size_t read_len = boost::asio::read(sp, boost::asio::buffer(read_buf,10), boost::asio::transfer_all(), serial_error);

           if(read_buf[1]==0x05)
           {
            pitch_angle = read_buf[2]*256+read_buf[3];
            // cout<<"205 pitch_angle : "<< pitch_angle <<endl;
             boost::posix_time::time_duration utc_timestamp = boost::posix_time::microsec_clock::universal_time()-epoch;
             append_data0(pitch_angle);
            // out<<utc_timestamp.total_milliseconds()<<"  ---- "<<pitch_angle<<endl;
            }

           if(read_buf[1]==0x06)
           {
            pitch_angle = read_buf[2]*256+read_buf[3];
            cout<<"206 pitch_angle : "<< pitch_angle <<endl;
            }

           if(read_buf[1]==0x00)
           {
            pitch_angle = read_buf[2]*256+read_buf[3];
            cout<<"400 pitch_angle : "<< pitch_angle <<endl;
            }
        }else {

         printf("head[0] %x\n", head[0] );
         printf("head[1] %x\n", head[1] );
        }
    }
}



int main(int argc, char *argv[])
{
    QApplication a(argc,argv);
    boost::asio::io_service              timer1_service;
    boost::asio::io_service              timer2_service;
    control motor(timer1_service,timer2_service);
    motor.show();

    sp.set_option(boost::asio::serial_port::baud_rate(921600));
    sp.set_option(boost::asio::serial_port::flow_control(boost::asio::serial_port::flow_control::none));
    sp.set_option(boost::asio::serial_port::parity(boost::asio::serial_port::parity::none));
    sp.set_option(boost::asio::serial_port::stop_bits(boost::asio::serial_port::stop_bits::one));
    sp.set_option(boost::asio::serial_port::character_size(8));

    serial_service.run();

    boost::thread  timer1Thread(boost::bind(&boost::asio::io_service::run, &timer1_service));
    boost::thread  timer2Thread(boost::bind(&boost::asio::io_service::run, &timer2_service));
    boost::thread  showThread(boost::bind(&control::readSerial, &motor));


//    showThread.join();
//    timer1Thread.join();




 return a.exec();
}
